package com.moro.lisp.typedefine;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
//import java.util.Map;
import java.util.Random;
import java.util.Scanner;

import com.moro.lisp.JLispData;
import com.moro.lisp.JLispFunctionName;
import com.moro.lisp.JLispMacroName;
import com.moro.lisp.JLispType;
import com.moro.lisp.os.Terminal;
import com.moro.lisp.tools.FunctionPool;
import com.moro.lisp.tools.MacroPool;
import com.moro.lisp.tools.SymbolPool;
import com.moro.lisp.typedefine.Error;

public class Function {
	
	
	private static int gensymNum = 1000;
	
	
	
	/*
	 * 杩欎釜瀛楁琛ㄧず璇ュ嚱鏁扮殑鍙傛暟缁撴灉鍥撅紝鐢ㄦ潵缂撳瓨鎵ц缁撴灉锛岀敤浠ユ彁鍗囨墽琛屾晥鐜�
	 */
	//private Map<JLispData, JLispData> answers;
	/*
	 * 杩欎釜瀛楁琛ㄧず杩欎釜鍑芥暟鐨勫悕瀛楋紝锛堝嚱鏁板悕瀛楅�氬父鎰忎箟涓嶅ぇ锛屼粎鏄负浜嗘爣璁板嚱鏁帮紝鍥犱负鍑芥暟鏃犳硶閫氳繃鍑芥暟鍚嶅瓧琚娇鐢級
	 */
	public JLispFunctionName functionName;
	
	/*
	 * 杩欎釜瀛楁琛ㄧず鍙傛暟鐨勪釜鏁版槸涓嶆槸鍥哄畾鐨勶紝涓簍rue琛ㄧず鏄紝涓篺alse琛ㄧず涓嶆槸
	 */
	public boolean isFixedArgs;
	
	/*
	 * 杩欎釜瀛楁琛ㄧず杩欎釜鍑芥暟鐨勫弬鏁板垪琛紝鍥犱负鍙傛暟鍒楄〃鍙兘鏄垪琛紝涓嶅彲鑳芥槸鍏跺畠鏁版嵁绫诲瀷	
	 */
	private Cons args;
	
	
	/*
	 * 杩欎釜瀛楁琛ㄧず杩欎釜鍑芥暟鐨勯棴鍖咃紝闂寘涓彧鑳芥槸鍘熷瓙	
	 */
	public List<Atom> closure;
	
	
	/*
	 * 杩欎釜瀛楁琛ㄧず杩欎釜鍑芥暟鐨勫弬鏁板垪琛紝鍙互涓哄師瀛恘il鐨勬儏鍐�
	 */
	private Atom nil;
	
	
	/*
	 * 杩欎釜鍙傛暟琛ㄧず鍑芥暟鐨勫嚱鏁颁綋锛岀敱涓�涓垨澶氫釜JavaLisp鏁版嵁缁勬垚锛屾墍浠ョ敤List闆嗗悎鏉ュ瓨鍌紝涓轰粈涔堜笉鐢–ons锛屽洜涓哄嚱鏁颁綋鍙兘鏄垪琛紝涔熷彲鑳芥槸鍏跺畠绫诲瀷鐨勬暟鎹�
	 */
	public List<JLispData> functionBodys;
	
	
	
	
	
	/*
	 * 杩欎釜瀛楁琛ㄧず璇ュ嚱鏁颁綔涓哄摢浜涘師瀛愮殑涓�鑸�硷紝鐢↙ist闆嗗悎瑁呰捣鏉ワ紝褰撲笉浣滀负浠讳綍鍘熷瓙鐨勪竴鑸�兼垨鍑芥暟鍊肩殑鏃跺�欙紝鍒欒鍑芥暟灏嗕粠缁堢鍑芥暟姹犱腑琚Щ闄わ紝锛堝洜涓烘棤娉曡寮曠敤锛岄偅杩欎釜鍑芥暟
	 * 灏嗘病鏈夊瓨鍦ㄧ殑鎰忎箟锛�
	 */
	public List<Atom> asSymbolValue;
	
	
	/*
	 * 杩欎釜瀛楁琛ㄧず璇ュ嚱鏁颁綔涓哄摢浜涘師瀛愮殑鍑芥暟鍊硷紝鐢↙ist闆嗗悎瑁呰捣鏉ワ紝褰撲笉浣滀负浠讳綍鍘熷瓙鐨勪竴鑸�兼垨鍑芥暟鍊肩殑鏃跺�欙紝鍒欒鍑芥暟灏嗕粠缁堢鍑芥暟姹犱腑琚Щ闄わ紝锛堝洜涓烘棤娉曡寮曠敤锛岄偅杩欎釜鍑芥暟
	 * 灏嗘病鏈夊瓨鍦ㄧ殑鎰忎箟锛�
	 */
	public List<Atom> asSymbolFunction;
	
	
	/**
	 * 鐗规澹版槑锛屾柊鍒涘缓涓�涓嚱鏁颁粎浠呭湪defun鎿嶄綔鐨勬椂鍊欐墠鑳界敤鍒帮紝鍥犱负JLisp涓嶆敮鎸乴ambda琛ㄨ揪寮忕敓鎴愬嚱鏁板璞�
	 * 锛岃��(setf func (symbol-function '+))绫讳技杩欐牱鐨勭粰绗﹀彿璧嬪�煎嚱鏁板�肩殑琛ㄨ揪寮忎篃浠呬粎鏄粠鍒殑绗�
	 * 鍙风殑鍑芥暟鍊间腑鎷胯繃鏉ヨ�屽凡锛屽悓鏍锋槸鍑芥暟姹犱腑鐨勫嚱鏁帮紝鍙笉杩囪繖涓嚱鏁板浜嗕竴涓鍙锋嫢鏈夎�屽凡
	 * @param functionName
	 * @param atom
	 */
	/*
	 * 瑕佸垱寤轰竴涓嚱鏁帮紝蹇呴』瑕佹彁渚涗竴涓鍙锋潵瀛樺偍鍑芥暟鍊硷紝
	 * 姝ゆ瀯閫犳柟娉曚负閫氳繃璁句负鍘熷瓙鐨勫嚱鏁板�兼潵鍒涘缓
	 */
	public Function(JLispFunctionName functionName,Atom atom,Cons args,List<JLispData> functionBodys, List<Atom> closure) {
		this.functionName = functionName;
		
		this.args = args;
		this.nil = null;
		this.isFixedArgs = isFixedArgs(this.args);
		this.functionBodys = functionBodys;

		this.asSymbolFunction = new ArrayList<Atom>();
		this.asSymbolValue = new ArrayList<Atom>();
		if(null == closure) {
			this.closure = null;
		}else {
			this.closure = closure;
			/*for(Atom a:this.closure) {
				a.symbolValues.bind(new JLispData(this, JLispType.FUNCTION));
			}*/
		}
		atom.setFunctionVal(new JLispData(this,JLispType.FUNCTION));//灏嗚鍘熷瓙鐨勫嚱鏁板�艰涓烘鍑芥暟
	}
	/*
	 * 瑕佸垱寤轰竴涓嚱鏁帮紝蹇呴』瑕佹彁渚涗竴涓鍙锋潵瀛樺偍鍑芥暟鍊硷紝
	 * 姝ゆ瀯閫犳柟娉曚负閫氳繃璁句负鍘熷瓙鐨勫嚱鏁板�兼潵鍒涘缓
	 * 锛堝綋鍙傛暟鍒楄〃涓虹┖鍒楄〃鍗冲師瀛愨�渘il鈥濈殑鏃跺�欙級
	 */
	public Function(JLispFunctionName functionName,Atom atom,Atom nil,List<JLispData> functionBodys, List<Atom> closure) {
		this.functionName = functionName;
		
		this.args = null;
		this.nil = nil;
		this.isFixedArgs = isFixedArgs(this.args);
		this.functionBodys = functionBodys;

		this.asSymbolFunction = new ArrayList<Atom>();
		this.asSymbolValue = new ArrayList<Atom>();
		if(null == closure) {
			this.closure = null;
		}else {
			this.closure = closure;
			/*for(Atom a:this.closure) {
				a.symbolValues.bind(new JLispData(this, JLispType.FUNCTION));
			}*/
		}
		atom.setFunctionVal(new JLispData(this,JLispType.FUNCTION));//灏嗚鍘熷瓙鐨勫嚱鏁板�艰涓烘鍑芥暟
	}
	private boolean isFixedArgs (Cons args) {
		return false;
	}
	/*
	 * 瑕佸垱寤轰竴涓嚱鏁帮紝蹇呴』瑕佹彁渚涗竴涓鍙峰�兼潵瀛樺偍鍑芥暟鍊硷紝
	 * 姝ゆ瀯閫犳柟娉曚负閫氳繃璁句负鍘熷瓙鐨勪竴鑸�兼潵鍒涘缓锛屽鏋渋sNewAction涓簍rue(澶勪簬鏂颁綔鐢ㄥ煙涓�)锛屽垯灏嗘鍑芥暟娣诲姞杩涘師瀛愮殑鍊兼爤锛屽惁鍒欓噸璁惧師瀛愬綋鍓嶅��
	 */
	/*public Function(JLispFunctionName functionName,Atom atom,boolean isNewAction) {
		if(isNewAction) {
			this.functionName = functionName;
			atom.setValue(new JLispData(this,JLispType.FUNCTION));//灏嗘鍑芥暟鈥濇坊鍔犫�滆繘璇ュ師瀛愮殑涓�鑸��
			this.args = args;
			this.functionBodys = functionBodys;
			this.asSymbolFunction = new ArrayList<Atom>();
			this.asSymbolValue = new ArrayList<Atom>();
			this.asSymbolValue.add(atom);//灏嗚鍘熷瓙娣诲姞鍒拌繖涓嚱鏁扮殑 asSymbolValue瀛楁锛岃〃绀鸿鍑芥暟鏄繖涓師瀛愮殑涓�鑸��
		}else {
			this.functionName = functionName;
			atom.resetValue(new JLispData(this,JLispType.FUNCTION));//灏嗚鍘熷瓙鐨勪竴鑸�尖�滈噸璁锯�濊涓烘鍑芥暟
			this.args = args;
			this.functionBodys = functionBodys;
			this.asSymbolFunction = new ArrayList<Atom>();
			this.asSymbolValue = new ArrayList<Atom>();
			this.asSymbolValue.add(atom);//灏嗚鍘熷瓙娣诲姞鍒拌繖涓嚱鏁扮殑 asSymbolValue瀛楁锛岃〃绀鸿鍑芥暟鏄繖涓師瀛愮殑涓�鑸��
		}
	}*/
	
	
	public JLispData eval() {//鎵�鏈夊嚱鏁板�肩殑杩斿洖鍊奸兘鏄嚜韬紝涓嶉渶瑕佺鍙锋睜
		return new JLispData(this, JLispType.FUNCTION);
	}
	
	
	public boolean isAlive() {//鑷鏈哄埗锛屽綋涓嶄綔涓轰换浣曚竴涓鍙风殑涓�鑸�兼垨鍑芥暟鍊兼椂琚涓烘槸鈥滈攢姣佲�濈殑锛岄渶瑕佷粠鍑芥暟姹犱腑绉婚櫎
		
		if(null == this.asSymbolFunction || null == this.asSymbolValue) {
			return false;
		}else if(this.asSymbolFunction.size() == 0 && this.asSymbolValue.size() == 0) {
			return false;
		}else {
			return true;
		}
		
	}
	
	
	
	/*
	 * 鎵ц杩欎釜鍑芥暟鐨勬柟娉曪紝浼犲叆鐨凧LispData宸茬粡琚眰鍊肩殑鍙傛暟鍊硷紝渚嬪(add (sub 1 1) 1 0)
	 * 鍒欐鏃朵紶閫掔粰add鍑芥暟鐨凧LispData涓� 鍘熷瓙2锛屽師瀛�1锛屽師瀛�0.鑰屼笉鏄垪琛紙sub 1 1锛夛紝鍘熷瓙1锛屽師瀛�0
	 * 娉ㄦ剰锛岃繖閲屾湁涓�涓噸鐐癸紝鏈夌殑鍑芥暟鍦ㄦ煇浜涙儏鍐典笅鏄笉瀵瑰弬鏁版眰鍊肩殑锛屼緥濡�(or t arg arg),褰撶涓�涓弬鏁版眰鍊间负t鏃讹紝鍒欏嚱鏁扮洿鎺�
	 * 杩斿洖t锛屽悗闈㈢殑鍙傛暟涓嶇敤姹傚�硷紝涓嶈繃杩欓噷涓嶇敤瀵硅繖绉嶅嚱鏁拌繘琛屽鐞嗭紝鍥犱负杩欑鍑芥暟鐩稿簲鐨勯�昏緫宸茬粡鍦ㄥ閮ㄨ澶勭悊骞惰繑鍥烇紝鎵�浠ュ湪鎵ц杩欑绫讳技鐨勭壒娈婇�昏緫鍑芥暟鏃堕渶瑕佽皟鐢ㄥ眰鐗规畩澶勭悊
	 * 鑰屼笉鑳藉皢鍙傛暟浼犲叆鍑芥暟鐨勫唴閮ㄨ繘琛屽鐞�
	 */
	public JLispData execute(JLispData[] args,SymbolPool symbolpool, FunctionPool functionPool, MacroPool macroPool) {//鍑芥暟鐨勬墽琛岄渶瑕佺鍙锋睜鍜屽嚱鏁版睜
		if(JLispFunctionName.CAR == this.functionName) {
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"car\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖鎴栬�呬笉涓篊ons
			 */
			if(null == args[0] || !(JLispType.CONS == args[0].type)) {//濡傛灉杩欎釜鍙傛暟涓虹┖鎴栬�呯被鍨嬩笉涓篊ons
				return new JLispData(new Error("The args need right JLispType data"),JLispType.ERROR);
			}
			
			return ((Cons)(args[0].data)).val;	
		}else if(JLispFunctionName.CDR == this.functionName) {
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"cdr\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			

			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖鎴栬�呬笉涓篊ons
			 */
			if(null == args[0] || !(JLispType.CONS == args[0].type)) {//濡傛灉杩欎釜鍙傛暟涓虹┖鎴栬�呯被鍨嬩笉涓篊ons
				return new JLispData(new Error("The args need right JLispType data"),JLispType.ERROR);
			}
			
			return ((Cons)(args[0].data)).another;
			
		}else if(JLispFunctionName.CONS == this.functionName) {
			int argsSize = args.length;
			if(!(argsSize == 2)) {
				return new JLispData(new Error("The function \"cons\" expected 2 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖,娉ㄦ剰杩欓噷涓嶄綔绫诲瀷妫�鏌ワ紝鍥犱负cons鍑芥暟鍙互鎺ュ彈涓嶄负绌虹殑浠绘剰JLispData鏁版嵁绫诲瀷
			 */
			if(null == args[0] || null == args[1]) {//濡傛灉杩欎釜鍙傛暟鏈夌┖鍊�
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			
			return new JLispData(new Cons(args[0], args[1]), JLispType.CONS);
			
			
		}else if(JLispFunctionName.INS == this.functionName) {
			int argsSize = args.length;
			if(!(argsSize == 2)) {
				return new JLispData(new Error("The function \"insert\" expected 2 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖,娉ㄦ剰杩欓噷涓嶄綔绫诲瀷妫�鏌ワ紝鍥犱负cons鍑芥暟鍙互鎺ュ彈涓嶄负绌虹殑浠绘剰JLispData鏁版嵁绫诲瀷
			 */
			if(null == args[0] || null == args[1]) {//濡傛灉杩欎釜鍙傛暟鏈夌┖鍊�
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			if(JLispType.CONS != args[0].type) {
				if(JLispType.ATOM != args[0].type) {
					return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
				}
				Atom atom = (Atom)(args[0].data);
				if(!"nil".equalsIgnoreCase(atom.name)) {
					return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
				}
				return new JLispData(new Cons(args[1], new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM)), JLispType.CONS);
			}else {
				Cons cons = (Cons)(args[0].data);
				Cons returnCons = cons.clone(cons);
				Cons setCons = (Cons)(returnCons.getDeepCons(returnCons.getLength() - 1).data);
				setCons.another = new JLispData(new Cons(args[1], setCons.another), JLispType.CONS);
				returnCons.flushConsLength();
				return new JLispData(returnCons, JLispType.CONS);
			}
			
			
		}else if(JLispFunctionName.IF == this.functionName) {//if鍑芥暟鍙兘鎺ュ彈涓や釜鍑芥暟鎴栦笁涓嚱鏁�
			int argsSize = args.length;
			if(argsSize < 2 || argsSize > 3) {
				return new JLispData(new Error("The function \"if\" expected 2 or 3 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			
			
		}else if(JLispFunctionName.ADD == this.functionName) {//+鍑芥暟鍙互鏈変换鎰忓涓弬鏁帮紝鏁呬笉浣滃弬鏁颁釜鏁板垽鏂�
			int argsSize = args.length;
			if(argsSize == 0) {//+鍑芥暟鍦ㄥ弬鏁颁釜鏁颁负0鐨勬椂鍊欒繑鍥�0鍘熷瓙
				return new JLispData(symbolpool.getSymbolByString("0"), JLispType.ATOM);
			}
			Atom ans = symbolpool.getSymbolByString("0");
			for(int i = 0;i < args.length;i++) {
				if(JLispType.ATOM != args[i].type) {//濡傛灉涓嶆槸鍘熷瓙锛屽垯褰�1澶勭悊
					if(JLispType.ERROR == args[i].type) {//濡傛灉鏄敊璇垯鐩存帴杩斿洖杩欎釜閿欒
						return args[i];
					}
					ans = add(ans, symbolpool.getSymbolByString("1"), symbolpool);
				}else {
					Atom atom = (Atom)(args[i].data);
					if("nil".equalsIgnoreCase(atom.name)) {//濡傛灉鏄痭il鍘熷瓙鍒欏綋0澶勭悊
						ans = add(ans, symbolpool.getSymbolByString("0"), symbolpool);
					}else if(atom.isNumber) {//濡傛灉鏄暟瀛楀師瀛愬垯鐩存帴褰撴暟瀛楀鐞�
						ans = add(ans, atom, symbolpool);//濡傛灉鏃笉鏄痭il鍘熷瓙涔熶笉鏄暟瀛楀師瀛愬垯褰�1澶勭悊
					}else {
						ans = add(ans, symbolpool.getSymbolByString("1"), symbolpool);
					}
				}
				
			}
			
			return new JLispData(ans, JLispType.ATOM);
			
		}else if(JLispFunctionName.SUB == this.functionName) {//-鍑芥暟鏈�灏戦渶瑕佷竴涓弬鏁帮紝濡傦紙- 1锛夎繑鍥�-1锛屽弬鏁�1琚綔涓烘渶鍚庝竴涓弬鏁拌�屼笉鏄涓�涓弬鏁帮紝绛夋晥浜庯紙- 0 1锛�
			int argsSize = args.length;
			if(argsSize == 0) {
				return new JLispData(new Error("The function \"sub\" expected more than 1 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			if(argsSize == 1) {//褰撳彧鏈変竴涓弬鏁版椂鍙傛暟绫诲瀷蹇呴』鏄暟瀛楋紝鍚﹀垯鎶ラ敊
				if(JLispType.ATOM != args[0].type) {
					return new JLispData(new Error("The function \"sub\" expected number as args"),JLispType.ERROR);
				}
				Atom num = (Atom)(args[0].data);
				if(num.isNumber) {
					return new JLispData(symbolpool.getSymbolByString("-" + num.name), JLispType.ATOM);
				}else {
					return new JLispData(new Error("The function \"sub\" expected number as args"),JLispType.ERROR);
				}
			}
			
			Atom ans = null;
			if(JLispType.ATOM != args[0].type) {
				ans = symbolpool.getSymbolByString("1");
			}else {
				ans = (Atom)(args[0].data);
				if(!ans.isNumber) {
					if("nil".equalsIgnoreCase(ans.name)) {
						ans = symbolpool.getSymbolByString("0");
					}else {
						ans = symbolpool.getSymbolByString("1");
					}
				}
			}
			
			for(int i = 1;i < args.length;i++) {
				if(JLispType.ATOM != args[i].type) {//濡傛灉涓嶆槸鍘熷瓙锛屽垯褰�1澶勭悊
					if(JLispType.ERROR == args[i].type) {//濡傛灉鏄敊璇垯鐩存帴杩斿洖杩欎釜閿欒
						return args[i];
					}
					ans = sub(ans, symbolpool.getSymbolByString("1"), symbolpool);
				}else {
					Atom atom = (Atom)(args[i].data);
					if("nil".equalsIgnoreCase(atom.name)) {//濡傛灉鏄痭il鍘熷瓙鍒欏綋0澶勭悊
						ans = sub(ans, symbolpool.getSymbolByString("0"), symbolpool);
					}else if(atom.isNumber) {//濡傛灉鏄暟瀛楀師瀛愬垯鐩存帴褰撴暟瀛楀鐞�
						ans = sub(ans, atom, symbolpool);//濡傛灉鏃笉鏄痭il鍘熷瓙涔熶笉鏄暟瀛楀師瀛愬垯褰�1澶勭悊
					}else {
						ans = sub(ans, symbolpool.getSymbolByString("1"), symbolpool);
					}
				}
			}
			return new JLispData(ans, JLispType.ATOM);
		}else if(JLispFunctionName.MUL == this.functionName) {//涔樺嚱鏁板彲浠ユ湁浠绘剰澶氫釜鍙傛暟锛屾晠涓嶄綔鍙傛暟涓暟鍒ゆ柇濡傦紙*锛夎繑鍥�1
			int argsSize = args.length;
			if(argsSize == 0) {//*鍑芥暟鍦ㄥ弬鏁颁釜鏁颁负0鐨勬椂鍊欒繑鍥�1鍘熷瓙
				return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
			}
			Atom ans = symbolpool.getSymbolByString("1");
			for(int i = 0;i < args.length;i++) {
				if(JLispType.ATOM != args[i].type) {//濡傛灉涓嶆槸鍘熷瓙锛屽垯褰�1澶勭悊
					if(JLispType.ERROR == args[i].type) {//濡傛灉鏄敊璇垯鐩存帴杩斿洖杩欎釜閿欒
						return args[i];
					}
					ans = mul(ans, symbolpool.getSymbolByString("1"), symbolpool);
				}else {
					Atom atom = (Atom)(args[i].data);
					if("nil".equalsIgnoreCase(atom.name)) {//濡傛灉鏄痭il鍘熷瓙鍒欏綋0澶勭悊
						ans = mul(ans, symbolpool.getSymbolByString("0"), symbolpool);
					}else if(atom.isNumber) {//濡傛灉鏄暟瀛楀師瀛愬垯鐩存帴褰撴暟瀛楀鐞�
						ans = mul(ans, atom, symbolpool);//濡傛灉鏃笉鏄痭il鍘熷瓙涔熶笉鏄暟瀛楀師瀛愬垯褰�1澶勭悊
					}else {
						ans = mul(ans, symbolpool.getSymbolByString("1"), symbolpool);
					}
				}
				
			}
			
			return new JLispData(ans, JLispType.ATOM);
		}else if(JLispFunctionName.DIV == this.functionName) {
			int argsSize = args.length;
			if(argsSize == 0) {
				return new JLispData(new Error("The function \"div\" expected more than 1 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			if(argsSize == 1) {//褰撳彧鏈変竴涓弬鏁版椂鍙傛暟绫诲瀷蹇呴』鏄暟瀛楋紝鍚﹀垯鎶ラ敊
				if(JLispType.ATOM != args[0].type) {
					return new JLispData(new Error("The function \"div\" expected number as args"),JLispType.ERROR);
				}
				Atom num = (Atom)(args[0].data);
				if(num.isNumber) {
					//鍒ゆ柇num鏄笉鏄暟瀛�0锛屾槸鐨勮瘽杩斿洖閿欒
					if(Double.valueOf(num.name) == 0) {
						return new JLispData(new Error("Division by zero!"),JLispType.ERROR);
					}
					return new JLispData(div(symbolpool.getSymbolByString("1"), num, symbolpool), JLispType.ATOM);
				}else {
					return new JLispData(new Error("The function \"div\" expected number as args"),JLispType.ERROR);
				}
			}
			Atom ans = null;
			if(JLispType.ATOM != args[0].type) {
				ans = symbolpool.getSymbolByString("1");
			}else {
				ans = (Atom)(args[0].data);
				if(!ans.isNumber) {
					if("nil".equals(ans.name)) {
						ans = symbolpool.getSymbolByString("0");
					}else {
						ans = symbolpool.getSymbolByString("1");
					}
				}
			}
			for(int i = 1;i < args.length;i++) {
				if(JLispType.ATOM != args[i].type) {//濡傛灉涓嶆槸鍘熷瓙锛屽垯褰�1澶勭悊
					if(JLispType.ERROR == args[i].type) {//濡傛灉鏄敊璇垯鐩存帴杩斿洖杩欎釜閿欒
						return args[i];
					}
					ans = div(ans, symbolpool.getSymbolByString("1"), symbolpool);
				}else {
					Atom atom = (Atom)(args[i].data);
					if("nil".equalsIgnoreCase(atom.name)) {//濡傛灉鏄痭il鍘熷瓙鍒欏綋0澶勭悊,鍙堝洜涓洪櫎鏁颁笉鑳戒负0锛屾墍浠ヨ繑鍥為敊璇�
						return new JLispData(new Error("Division by zero!"),JLispType.ERROR);
					}else if(atom.isNumber) {//濡傛灉鏄暟瀛楀師瀛愬垯鐩存帴褰撴暟瀛楀鐞�
						if(Double.valueOf(atom.name) == 0) {
							return new JLispData(new Error("Division by zero!"),JLispType.ERROR);
						}
						ans = div(ans, atom, symbolpool);//濡傛灉鏃笉鏄痭il鍘熷瓙涔熶笉鏄暟瀛楀師瀛愬垯褰�1澶勭悊
					}else {
						ans = div(ans, symbolpool.getSymbolByString("1"), symbolpool);
					}
				}
			}
			return new JLispData(ans, JLispType.ATOM);
		}else if(JLispFunctionName.MOD == this.functionName) {
			int argsSize = args.length;
			if(argsSize == 0) {
				return new JLispData(new Error("The function \"mod\" expected more than 1 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			if(argsSize == 1) {//褰撳彧鏈変竴涓弬鏁版椂鍙傛暟绫诲瀷蹇呴』鏄暟瀛楋紝鍚﹀垯鎶ラ敊
				if(JLispType.ATOM != args[0].type) {
					return new JLispData(new Error("The function \"mod\" expected number as args"),JLispType.ERROR);
				}
				Atom num = (Atom)(args[0].data);
				if(num.isNumber) {
					//鍒ゆ柇num鏄笉鏄暟瀛�0锛屾槸鐨勮瘽杩斿洖閿欒
					if(Double.valueOf(num.name) == 0) {
						return new JLispData(new Error("Division by zero!"),JLispType.ERROR);
					}
					return new JLispData(mod(symbolpool.getSymbolByString("1"), num, symbolpool), JLispType.ATOM);
				}else {
					return new JLispData(new Error("The function \"mod\" expected number as args"),JLispType.ERROR);
				}
			}
			Atom ans = null;
			if(JLispType.ATOM != args[0].type) {
				ans = symbolpool.getSymbolByString("1");
			}else {
				ans = (Atom)(args[0].data);
				if(!ans.isNumber) {
					if("nil".equals(ans.name)) {
						ans = symbolpool.getSymbolByString("0");
					}else {
						ans = symbolpool.getSymbolByString("1");
					}
				}
			}
			for(int i = 1;i < args.length;i++) {
				if(JLispType.ATOM != args[i].type) {//濡傛灉涓嶆槸鍘熷瓙锛屽垯褰�1澶勭悊
					if(JLispType.ERROR == args[i].type) {//濡傛灉鏄敊璇垯鐩存帴杩斿洖杩欎釜閿欒
						return args[i];
					}
					ans = mod(ans, symbolpool.getSymbolByString("1"), symbolpool);
				}else {
					Atom atom = (Atom)(args[i].data);
					if("nil".equalsIgnoreCase(atom.name)) {//濡傛灉鏄痭il鍘熷瓙鍒欏綋0澶勭悊,鍙堝洜涓洪櫎鏁颁笉鑳戒负0锛屾墍浠ヨ繑鍥為敊璇�
						return new JLispData(new Error("Division by zero!"),JLispType.ERROR);
					}else if(atom.isNumber) {//濡傛灉鏄暟瀛楀師瀛愬垯鐩存帴褰撴暟瀛楀鐞�
						if(Double.valueOf(atom.name) == 0) {
							return new JLispData(new Error("Division by zero!"),JLispType.ERROR);
						}
						ans = mod(ans, atom, symbolpool);//濡傛灉鏃笉鏄痭il鍘熷瓙涔熶笉鏄暟瀛楀師瀛愬垯褰�1澶勭悊
					}else {
						ans = mod(ans, symbolpool.getSymbolByString("1"), symbolpool);
					}
				}
			}
			return new JLispData(ans, JLispType.ATOM);
			
			
		}else if(JLispFunctionName.AND == this.functionName) {
			return new JLispData(new Error("Unknow Error!"), JLispType.ERROR);
		}else if(JLispFunctionName.OR == this.functionName) {//and鍜宱r鍑芥暟閮藉彲浠ユ湁浠绘剰澶氫釜鍙傛暟锛屾晠涓嶄綔鍒ゆ柇
			return new JLispData(new Error("Unknow Error!"), JLispType.ERROR);
		}else if(JLispFunctionName.PROGN == this.functionName) {//progn鍑芥暟鍙互鏈変换鎰忓涓嚱鏁帮紝鏁呬笉浣滃垽鏂�
			/*
			 * 濡傛灉鍙傛暟鏁扮粍涓虹┖鎴栬�呮暟缁勪腑娌℃湁鍊硷紝鍒欑洿鎺ヨ繑鍥瀗il鍘熷瓙
			 */
			if(null == args || args.length == 0) {
				return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
			}
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖
			 */
			for(JLispData arg:args) {
				if(null == arg) {
					return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
				}
			}
			return args[args.length - 1];//鐩存帴杩斿洖鏈�鍚庝竴涓��
		}else if(JLispFunctionName.MORE == this.functionName) {
			int argsSize = args.length;
			if(argsSize == 0) {
				return new JLispData(new Error("The function \"more\" expected more than 1 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖鎴栬�呮纭殑绫诲瀷
			 */
			for(JLispData arg:args) {
				if(null == arg || !(JLispType.ATOM == arg.type) || !(((Atom)(arg.data)).isNumber)) {
					return new JLispData(new Error("The function \"more\" needs right JLispType data"),JLispType.ERROR);
				}
			}
			if(argsSize == 1) {
				return new JLispData(symbolpool.getSymbolByString("t"), JLispType.ATOM);
			}
			for(int i = 0;i < argsSize - 1;i++) {
				Atom arg0 = (Atom)(args[i].data);
				Atom arg1 = (Atom)(args[i + 1].data);
				boolean isMore = more(arg0, arg1);
				if(!isMore) {//濡傛灉涓嶅ぇ浜庡垯杩斿洖nil鍘熷瓙
					return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
				}
			}
			
			return new JLispData(symbolpool.getSymbolByString("t"), JLispType.ATOM);
		}else if(JLispFunctionName.LESS == this.functionName) {
			int argsSize = args.length;
			if(argsSize == 0) {
				return new JLispData(new Error("The function \"less\" expected more than 1 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖鎴栬�呮纭殑绫诲瀷
			 */
			for(JLispData arg:args) {
				if(null == arg || !(JLispType.ATOM == arg.type) || !(((Atom)(arg.data)).isNumber)) {
					return new JLispData(new Error("The function \"less\" needs right JLispType data"),JLispType.ERROR);
				}
			}
			if(argsSize == 1) {
				return new JLispData(symbolpool.getSymbolByString("t"), JLispType.ATOM);
			}
			for(int i = 0;i < argsSize - 1;i++) {
				Atom arg0 = (Atom)(args[i].data);
				Atom arg1 = (Atom)(args[i + 1].data);
				boolean isLess = less(arg0, arg1);
				if(!isLess) {//濡傛灉涓嶅皬浜庡垯杩斿洖nil鍘熷瓙
					return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
				}
			}
			
			return new JLispData(symbolpool.getSymbolByString("t"), JLispType.ATOM);
			
		}else if(JLispFunctionName.EQ == this.functionName) {//eq鍑芥暟鍙兘鏈�2涓弬鏁�
			int argsSize = args.length;
			if(!(argsSize == 2)) {
				return new JLispData(new Error("The function \"eq\" expected 2 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖
			 */
			if(null == args[0] || null == args[1]) {
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			if(args[0].data == args[1].data) {
				return new JLispData(symbolpool.getSymbolByString("t"), JLispType.ATOM);
			}else {
				if(JLispType.ATOM == args[0].type && JLispType.ATOM == args[1].type) {
					if(((Atom)(args[0].data)).name.equalsIgnoreCase(((Atom)(args[1].data)).name)) {
						return new JLispData(symbolpool.getSymbolByString("t"), JLispType.ATOM);
					}
					Atom isNum = (Atom)(args[0].data);
					Atom isNum1 = (Atom)(args[1].data);
					if(isNum.isNumber && isNum.isNumber) {
						if(eqNum(isNum, isNum1)) {
							return new JLispData(symbolpool.getSymbolByString("t"), JLispType.ATOM);
						}
						return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
					}
					return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
				}
				return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
			}
			
		}else if(JLispFunctionName.PRINT == this.functionName) {//浠ヤ笂閮芥槸瑙ｉ噴鍣ㄨ嚜甯︾殑鍩烘湰鍑芥暟锛岀敱鍑芥暟姹犲垵濮嬪寲鐨勮繃绋嬩腑鑷姩鍒涘缓锛屽悗闈笉鍏佽鍒涘缓涓庤繖浜涘熀鏈嚱鏁板悓鍑芥暟鍚嶇殑鍑芥暟
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"print\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖
			 */
			if(null == args[0]) {
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			//Terminal.print(args[0]);
			System.out.print(Terminal.getStringFromData(args[0]));
			return args[0];
			
		}else if(JLispFunctionName.SYMBOLVALUE == this.functionName) {//浠ヤ笂閮芥槸瑙ｉ噴鍣ㄨ嚜甯︾殑鍩烘湰鍑芥暟锛岀敱鍑芥暟姹犲垵濮嬪寲鐨勮繃绋嬩腑鑷姩鍒涘缓锛屽悗闈笉鍏佽鍒涘缓涓庤繖浜涘熀鏈嚱鏁板悓鍑芥暟鍚嶇殑鍑芥暟
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"symbolvalue\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖
			 */
			if(null == args[0]) {
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			if(!(JLispType.ATOM == args[0].type)) {//濡傛灉鍙傛暟绫诲瀷涓嶄负鍘熷瓙
				return new JLispData(new Error("The function \"symbolvalue\" expected data of Atom, but found other type"),JLispType.ERROR);
			}
			Atom atom = (Atom) (args[0].data);
			JLispData returnValue = atom.eval();
			if(null == returnValue) {
				return new JLispData(new Error("The atom \""+atom.name+"\" has no general value"),JLispType.ERROR);
			}
			return returnValue;
		}else if(JLispFunctionName.SYMBOLFUNCTION == this.functionName) {//浠ヤ笂閮芥槸瑙ｉ噴鍣ㄨ嚜甯︾殑鍩烘湰鍑芥暟锛岀敱鍑芥暟姹犲垵濮嬪寲鐨勮繃绋嬩腑鑷姩鍒涘缓锛屽悗闈笉鍏佽鍒涘缓涓庤繖浜涘熀鏈嚱鏁板悓鍑芥暟鍚嶇殑鍑芥暟
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"symbolfunction\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖
			 */
			if(null == args[0]) {
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			if(!(JLispType.ATOM == args[0].type)) {//濡傛灉鍙傛暟绫诲瀷涓嶄负鍘熷瓙
				return new JLispData(new Error("The function \"symbolfunction\" expected data of Atom, but found other type"),JLispType.ERROR);
			}
			Atom atom = (Atom) (args[0].data);
			JLispData returnValue = atom.functionEval();
			if(null == returnValue) {
				return new JLispData(new Error("The atom \""+atom.name+"\" has no function value or macro value"),JLispType.ERROR);
			}
			return returnValue;
		}else if(JLispFunctionName.EVAL == this.functionName) {//浠ヤ笂閮芥槸瑙ｉ噴鍣ㄨ嚜甯︾殑鍩烘湰鍑芥暟锛岀敱鍑芥暟姹犲垵濮嬪寲鐨勮繃绋嬩腑鑷姩鍒涘缓锛屽悗闈笉鍏佽鍒涘缓涓庤繖浜涘熀鏈嚱鏁板悓鍑芥暟鍚嶇殑鍑芥暟
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"eval\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖
			 */
			if(null == args[0]) {
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			return args[0].eval(symbolpool, functionPool, macroPool);
		}else if(JLispFunctionName.ATOM == this.functionName) {//浠ヤ笂閮芥槸瑙ｉ噴鍣ㄨ嚜甯︾殑鍩烘湰鍑芥暟锛岀敱鍑芥暟姹犲垵濮嬪寲鐨勮繃绋嬩腑鑷姩鍒涘缓锛屽悗闈笉鍏佽鍒涘缓涓庤繖浜涘熀鏈嚱鏁板悓鍑芥暟鍚嶇殑鍑芥暟
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"atom\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖
			 */
			if(null == args[0]) {
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			if(JLispType.ATOM == args[0].type) {
				return new JLispData(symbolpool.getSymbolByString("t"), JLispType.ATOM);
			}else {
				return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
			}
			
		}else if(JLispFunctionName.CONSP == this.functionName) {//浠ヤ笂閮芥槸瑙ｉ噴鍣ㄨ嚜甯︾殑鍩烘湰鍑芥暟锛岀敱鍑芥暟姹犲垵濮嬪寲鐨勮繃绋嬩腑鑷姩鍒涘缓锛屽悗闈笉鍏佽鍒涘缓涓庤繖浜涘熀鏈嚱鏁板悓鍑芥暟鍚嶇殑鍑芥暟
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"consp\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖
			 */
			if(null == args[0]) {
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			
			if(JLispType.CONS == args[0].type) {//濡傛灉鍙傛暟鐨勭被鍨嬫槸Cons锛屽垯杩斿洖t鍘熷瓙锛屽惁鍒欒繑鍥瀗il鍘熷瓙
				return new JLispData(symbolpool.getSymbolByString("t"),JLispType.ATOM);
			}else {
				return new JLispData(symbolpool.getSymbolByString("nil"),JLispType.ATOM);
			}
		}else if(JLispFunctionName.NUMBERP == this.functionName) {//浠ヤ笂閮芥槸瑙ｉ噴鍣ㄨ嚜甯︾殑鍩烘湰鍑芥暟锛岀敱鍑芥暟姹犲垵濮嬪寲鐨勮繃绋嬩腑鑷姩鍒涘缓锛屽悗闈笉鍏佽鍒涘缓涓庤繖浜涘熀鏈嚱鏁板悓鍑芥暟鍚嶇殑鍑芥暟
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"numberp\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			/*
			 * 鍒ゆ柇鍙傛暟鏄惁涓虹┖
			 */
			if(null == args[0]) {
				return new JLispData(new Error("The args need JLispType data"),JLispType.ERROR);
			}
			
			 /*
			  * 濡傛灉鍙傛暟鍊间笉鏄竴涓師瀛愶紝閭ｄ箞鑲畾涓嶆槸鏁板瓧锛屽垯杩斿洖鍘熷瓙nil
			  */
			if(!(JLispType.ATOM == args[0].type)) {
				return new JLispData(symbolpool.getSymbolByString("nil"),JLispType.ATOM);
			}else {
				if(((Atom)(args[0].data)).isNumber) {
					return new JLispData(symbolpool.getSymbolByString("t"),JLispType.ATOM);
				}else {
					return new JLispData(symbolpool.getSymbolByString("nil"),JLispType.ATOM);
				}
			}
		}else if(JLispFunctionName.LIST == this.functionName) {
			int argsSize = args.length;
			if(argsSize == 0) {
				return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
			}
			return new JLispData(new Cons(args, symbolpool.getSymbolByString("nil")), JLispType.CONS);
		}else if(JLispFunctionName.GENSYM == this.functionName) {//杩斿洖涓�涓殢鏈虹殑绗﹀彿
			/*
			 * 浠ｇ爜
			 */
			int symbolsSize = symbolpool.getSymbolsSize();
			Atom atom = symbolpool.getSymbolByString("gensym"+Function.gensymNum++);
			while(!(symbolpool.getSymbolsSize() > symbolsSize)) {
				atom = symbolpool.getSymbolByString("gensym"+Function.gensymNum++);
			}
			return new JLispData(atom, JLispType.ATOM);
		}else if(JLispFunctionName.RAND == this.functionName) {//杩斿洖涓�涓殢鏈虹殑鏁板瓧
			int argsSize = args.length;
			if(argsSize > 1) {
				return new JLispData(new Error("The function \"rand\" expected 0 or 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			Random rd = new Random();
			if(argsSize == 0) {
				return new JLispData(symbolpool.getSymbolByString(""+rd.nextDouble()), JLispType.ATOM);
			}else {
				if(JLispType.ATOM == args[0].type) {
					Atom atom = (Atom)(args[0].data);
					if(atom.isNumber) {
						if(atom.name.contains(".")) {
							new Error("The function \"rand\" needs int number or cons to be the arg");
							return new JLispData(symbolpool.getSymbolByString(""+rd.nextDouble()), JLispType.ATOM);
						}else {
							int num = Integer.valueOf(atom.name);
							if(num == 0) {
								new Error("Zero can not be the random range");
								return new JLispData(symbolpool.getSymbolByString(""+rd.nextDouble()), JLispType.ATOM);
							}
							return new JLispData(symbolpool.getSymbolByString(""+rd.nextInt(num)), JLispType.ATOM);
						}
					}else {
						new Error("The function \"rand\" needs int number or cons to be the arg");
						return new JLispData(symbolpool.getSymbolByString(""+rd.nextDouble()), JLispType.ATOM);
					}
				}else if(JLispType.CONS == args[0].type) {
					Cons cons = (Cons)(args[0].data);
					return cons.getItemById(rd.nextInt(cons.getLength()));
				}else {
					new Error("The function \"rand\" needs int number or cons to be the arg");//鍙傛暟涓嶅锛屼骇鐢熶竴涓鍛�
					return new JLispData(symbolpool.getSymbolByString(""+rd.nextDouble()), JLispType.ATOM);
				}
			}
		}else if(JLispFunctionName.PARSELIST == this.functionName) {//鐩存帴鎵ц杩欎釜鍑芥暟浼氳繑鍥炰竴涓敊璇紝杩欎釜鍑芥暟搴旇鍦╨ist鍑芥暟涓氨琚鐞�
			return new JLispData(new Error("Commat is illegal outside of backquote"), JLispType.ERROR);
		}else if(JLispFunctionName.NTH == this.functionName) {
			int argsSize = args.length;
			if(!(argsSize == 2)) {
				return new JLispData(new Error("The function \"nth\" expected 2 args, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			if(JLispType.ATOM != args[0].type) {
				return new JLispData(new Error("The function \"nth\" needs an number to be the index of list"),JLispType.ERROR);
			}
			Atom atom = (Atom)(args[0].data);
			if(!atom.isNumber) {
				return new JLispData(new Error("The function \"nth\" needs an number to be the index of list"),JLispType.ERROR);
			}
			int index = (int)(Double.valueOf(atom.name).doubleValue());
			//index = index >= 0 ? index : -index;
			if(JLispType.CONS != args[1].type) {//蹇呴』鏄痗ons绫诲瀷锛宯il鍘熷瓙涔熶笉琛�
				return new JLispData(new Error("The function \"nth\" needs a list"),JLispType.ERROR);
			}
			Cons cons = (Cons)(args[1].data);
			if(index >= cons.getLength()) {
				return new JLispData(new Error("Can not get the item of this cons,Because of IndexOutOfBoundsError"),JLispType.ERROR);
			}
			return cons.getItemById(index);
		}else if(JLispFunctionName.TIME == this.functionName) {
			return new JLispData(new Error("The function time can not execute direct"), JLispType.ERROR);
		}else if(JLispFunctionName.APPLY == this.functionName) {
			return new JLispData(new Error("The function apply can not execute direct"), JLispType.ERROR);
		}else if(JLispFunctionName.FUNCALL == this.functionName) {
			return new JLispData(new Error("The function funcall can not execute direct"), JLispType.ERROR);
		}else if(JLispFunctionName.LENGTH == this.functionName) {
			int argsSize = args.length;
			if(!(argsSize == 1)) {
				return new JLispData(new Error("The function \"length\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			if(JLispType.CONS != args[0].type) {
				if(JLispType.ATOM == args[0].type) {
					Atom a = (Atom)(args[0].data);
					if("nil".equalsIgnoreCase(a.name)) {
						return new JLispData(symbolpool.getSymbolByString("0"), JLispType.ATOM);
					}
				}
				return new JLispData(new Error("The function \"length\" needs a list"), JLispType.ERROR);
			}
			Cons cons = (Cons)(args[0].data);
			return new JLispData(symbolpool.getSymbolByString(cons.getLength()+""), JLispType.ATOM);
		}else if(JLispFunctionName.MACROEXPAND == this.functionName) {
			int argsSize = args.length;
			if(argsSize != 1) {
				return new JLispData(new Error("The function \"macroexpand\" expected 1 arg, but found "+argsSize+" arg"),JLispType.ERROR);
			}
			if(JLispType.CONS != args[0].type) {//濡傛灉鍙傛暟涓嶆槸鍒楄〃锛屽垯鐩存帴杩斿洖
				return args[0];
			}
			Cons expr = (Cons)(args[0].data);
			int kind = kindOfCons(expr);
			if(kind == 0) {//濡傛灉鏄櫘閫氬垪琛ㄥ垯鐩存帴杩斿洖
				return args[0];
			}else if(kind == 1) {//濡傛灉鏄嚱鏁板垪琛ㄥ垯閫掑綊
				for(int i = 1;i < expr.getLength();i++) {
					expr.setItemById(i, execute(new JLispData[]{expr.getItemById(i)}, symbolpool, functionPool, macroPool));
				}
				return args[0];
			}else {//濡傛灉鏄畯鍒楄〃
				Macro macro = (Macro)(((Atom)(expr.getItemById(0).data)).functionEval().data);
				if(JLispMacroName.CUSTOMIZE == macro.macroName) {
					JLispData[] macroArgs = new JLispData[expr.getLength() - 1];
					for(int i = 1;i < expr.getLength();i++) {
						macroArgs[i - 1] = expr.getItemById(i);
					}
					return execute(new JLispData[]{macro.execute(macroArgs, symbolpool, functionPool, macroPool)}, symbolpool, functionPool, macroPool);
				}else if(JLispMacroName.SETQ == macro.macroName) {
					if(expr.getLength() < 3) {
						return args[0];
					}
					for(int i = 2;i < expr.getLength();i += 2) {
						expr.setItemById(i, execute(new JLispData[]{expr.getItemById(i)}, symbolpool, functionPool, macroPool));
					}
					return args[0];
				}else if(JLispMacroName.SETF == macro.macroName) {
					for(int i = 1;i < expr.getLength();i++) {
						expr.setItemById(i, execute(new JLispData[]{expr.getItemById(i)}, symbolpool, functionPool, macroPool));
					}
					return args[0];
				}else if(JLispMacroName.DO == macro.macroName) {
					JLispData isArgsCons = null;
					JLispData isConditionCons = null;
					if(expr.getLength() > 1) {
						isArgsCons = expr.getItemById(1);
					}
					if(expr.getLength() > 2) {
						isConditionCons = expr.getItemById(2);
					}
					if(null != isArgsCons) {//濡傛灉鍙傛暟鍒楄〃涓嶄负绌�
						if(JLispType.CONS == isArgsCons.type) {//濡傛灉鍙傛暟鍒楄〃鏄垪琛�
							Cons argsCons = (Cons)(isArgsCons.data);
							for(int i = 0;i < argsCons.getLength();i++) {//閬嶅巻鍙傛暟鍒楄〃鐨勫厓绱�
								JLispData isArgCons = argsCons.getItemById(i);
								if(JLispType.CONS == isArgCons.type) {//濡傛灉鏈夊厓绱犳槸鍒楄〃
									Cons argCons = (Cons)(isArgCons.data);
									if(argCons.getLength() > 1) {//濡傛灉璇ュ垪琛ㄩ暱搴﹀ぇ浜�1
										for(int j = 1;j < argCons.getLength();j++) {//浠庣储寮曞�间负1寮�濮嬭繘琛岃В鏋�
											argCons.setItemById(j, execute(new JLispData[]{argCons.getItemById(j)}, symbolpool, functionPool, macroPool));
										}
									}
								}
							}
						}
					}
					if(null != isConditionCons) {//濡傛灉鏉′欢鍒楄〃涓嶄负绌�
						if(JLispType.CONS == isConditionCons.type) {//濡傛灉鏉′欢鍒楄〃鏄垪琛�
							Cons conditionCons = (Cons)(isConditionCons.data);
							for(int i = 0;i < conditionCons.getLength();i++) {//浠庣储寮曞�间负0寮�濮嬭繘琛岃В鏋�
								conditionCons.setItemById(i, execute(new JLispData[]{conditionCons.getItemById(i)}, symbolpool, functionPool, macroPool));
							}
						}
					}
					if(expr.getLength() > 3) {
						for(int i = 3;i < expr.getLength();i++) {
							expr.setItemById(i, execute(new JLispData[]{expr.getItemById(i)}, symbolpool, functionPool, macroPool));
						}
					}
					return args[0];
				}else if(JLispMacroName.LET == macro.macroName) {
					JLispData isArgsCons = null;
					if(expr.getLength() > 1) {
						isArgsCons = expr.getItemById(1);
					}
					if(null != isArgsCons) {//濡傛灉鍙傛暟鍒楄〃涓嶄负绌�
						if(JLispType.CONS == isArgsCons.type) {//濡傛灉鍙傛暟鍒楄〃鏄垪琛�
							Cons argsCons = (Cons)(isArgsCons.data);
							for(int i = 0;i < argsCons.getLength();i++) {//閬嶅巻鍙傛暟鍒楄〃鐨勫厓绱�
								JLispData isArgCons = argsCons.getItemById(i);
								if(JLispType.CONS == isArgCons.type) {//濡傛灉鏈夊厓绱犳槸鍒楄〃
									Cons argCons = (Cons)(isArgCons.data);
									if(argCons.getLength() > 1) {//濡傛灉璇ュ垪琛ㄩ暱搴﹀ぇ浜�1
										for(int j = 1;j < argCons.getLength();j++) {//浠庣储寮曞�间负1寮�濮嬭繘琛岃В鏋�
											argCons.setItemById(j, execute(new JLispData[]{argCons.getItemById(j)}, symbolpool, functionPool, macroPool));
										}
									}
								}
							}
						}
					}
					if(expr.getLength() > 2) {
						for(int i = 2;i < expr.getLength();i++) {
							expr.setItemById(i, execute(new JLispData[]{expr.getItemById(i)}, symbolpool, functionPool, macroPool));
						}
					}
					return args[0];
				}else {
					return args[0];
				}
			}
		}else if(JLispFunctionName.LOAD == this.functionName) {
			int argsSize = args.length;
			if(argsSize == 0) {
				return new JLispData(symbolpool.getSymbolByString("nil"),JLispType.ATOM);
			}
			File file = null;
			JLispData returnValue = new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
			for(int i = 0;i < argsSize;i++) {
				if(JLispType.CONS != args[i].type) {
					new Error("\"" + Terminal.getStringFromData(args[i]) + "\" is not filepath");
					continue;
				}
				Cons cons = (Cons)(args[i].data);
				String path = getPathFromCons(cons);
				file = new File(path);
				if(!file.exists()) {
					new Error("Can not find the file from the path:\""+path+"\"");
					continue;
				}
				String format = null;
				try {
					format = codeString(path);
				} catch (Exception e) {
					// TODO Auto-generated catch block
					new Error("FileException");
					e.printStackTrace();
					continue;
				}
				if(null == format || !"UTF-8".equals(format)) {
					new Error("FileFormatException,try to change format to \"UTF-8\"");
					continue;
				}
				FileReader reader = null;
				BufferedReader bReader = null;
				StringBuilder sb = new StringBuilder();
				try {
					reader = new FileReader(file);
					bReader = new BufferedReader(reader);
				} catch (FileNotFoundException e) {
					// TODO Auto-generated catch block
					new Error("FileNotFoundException!");
					e.printStackTrace();
					try {
						reader.close();
						bReader.close();
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						new Error("IOException!");
						e.printStackTrace();
						e1.printStackTrace();
					}
					continue;
				}
				String s = "";
				try {
					while ((s = bReader.readLine()) != null) {//閫愯璇诲彇鏂囦欢鍐呭锛屼笉璇诲彇鎹㈣绗﹀拰鏈熬鐨勭┖鏍�
						if(s.length() > 0)
						if(65279 == s.charAt(0)) {
							s = s.substring(1);
						}
					    sb.append(s + "\n");//灏嗚鍙栫殑瀛楃涓叉坊鍔犳崲琛岀鍚庣疮鍔犲瓨鏀惧湪缂撳瓨涓�
					}
					bReader.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					new Error("IOException!");
					e.printStackTrace();
					continue;
				}
				String context = sb.toString();
				context = context.replace("；", ";");
				String[] exprs = context.split(";");
				
				JLispData ans = null;
				for(String expr: exprs) {
					if("".equals(expr)) {
						continue;
					}
					String exp = toRightExpr(expr);
					if("".equals(exp)) {
						continue;
					}
					ans = Terminal.getDataFromString(exp.trim(), symbolpool, functionPool, macroPool).eval(symbolpool, functionPool, macroPool);
				}
				returnValue = ans;
			}
			return returnValue;
		}else if(JLispFunctionName.ERROR == this.functionName) {
			//int argsSize = args.length;
			StringBuilder sb = new StringBuilder();
			for(int i = 0;i < args.length;i++) {
				if(JLispType.ERROR == args[i].type) {
					return args[i];
				}
				String text = Terminal.getStringFromData(args[i]);
				if(JLispType.CONS == args[i].type) {
					text = text.substring(1, text.length() - 1);
				}
				if(i < args.length - 1) {
					text += " ";
				}
				sb.append(text);
			}
			return new JLispData(new Error(sb.toString()), JLispType.ERROR);
		}else if(JLispFunctionName.REMOVE == this.functionName) {
			int argsSize = args.length;
			if(argsSize != 2) {
				return new JLispData(new Error("The function \"remove\" expected 2 args, but found "+argsSize+" arg"), JLispType.ERROR);
			}
			if(JLispType.CONS != args[0].type) {
				return new JLispData(new Error("Can not remove the item from the data expect cons"), JLispType.ERROR);
			}
			if(JLispType.ATOM != args[1].type) {
				return new JLispData(new Error("Can not remove the item by the type expect number"), JLispType.ERROR);
			}
			Atom a = (Atom)(args[1].data);
			if(!a.isNumber) {
				return new JLispData(new Error("Can not remove the item by the type expect number"), JLispType.ERROR);
			}
			int index = (int)(Double.valueOf(a.name).doubleValue());
			Cons cons = (Cons)(args[0].data);
			if(index < 0 || index >= cons.getLength()) {
				return new JLispData(new Error("Can not remove the item form the cons,Because of IndexOutOfBoundsError"),JLispType.ERROR);
			}
			if(index == 0) {
				if(index == cons.getLength() - 1) {
					args[0].data = symbolpool.getSymbolByString("nil");
					args[0].type = JLispType.ATOM;
				}else {
					cons.val = ((Cons)(cons.getRestById(1).data)).val;
					cons.another = ((Cons)(cons.getRestById(1).data)).another;
					cons.flushConsLength();
				}
			}else {
				((Cons)(cons.getRestById(index - 1).data)).another = ((Cons)(cons.getRestById(index).data)).another;
				cons.flushConsLength();
			}
			return args[0];
		}else if(JLispFunctionName.ARGUMENTSIZE == this.functionName) {
			int argsSize = args.length;
			if(argsSize != 1) {
				return new JLispData(new Error("The function \"argumentsize\" expected 1 arg, but found "+argsSize+" arg"), JLispType.ERROR);
			}
			if(JLispType.FUNCTION != args[0].type && JLispType.MACRO != args[0].type) {
				return new JLispData(new Error("The function \"argumentsize\" expected function or macro as arg"), JLispType.ERROR);
			}
			if(JLispType.FUNCTION == args[0].type) {
				Function fun = (Function)(args[0].data);
				if(JLispFunctionName.CAR == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.CDR == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.CONS == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("2"), JLispType.ATOM);
				}else if(JLispFunctionName.INS == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("2"), JLispType.ATOM);
				}else if(JLispFunctionName.IF == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("3"), JLispType.ATOM);
				}else if(JLispFunctionName.ADD == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.SUB == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.MUL == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.DIV == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.MOD == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.AND == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.OR == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.PROGN == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.MORE == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.LESS == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.EQ == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("2"), JLispType.ATOM);
				}else if(JLispFunctionName.PRINT == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.SYMBOLVALUE == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.SYMBOLFUNCTION == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.EVAL == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.ATOM == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.CONSP == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.NUMBERP == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.LIST == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.GENSYM == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("0"), JLispType.ATOM);
				}else if(JLispFunctionName.RAND == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.PARSELIST == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.NTH == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("2"), JLispType.ATOM);
				}else if(JLispFunctionName.TIME == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.APPLY == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("2"), JLispType.ATOM);
				}else if(JLispFunctionName.FUNCALL == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.LENGTH == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.MACROEXPAND == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.LOAD == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.ERROR == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispFunctionName.REMOVE == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("2"), JLispType.ATOM);
				}else if(JLispFunctionName.ARGUMENTSIZE == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.SLEEP == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.TYPE == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispFunctionName.IN == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("0"), JLispType.ATOM);
				}else if(JLispFunctionName.DEBUG == fun.functionName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else {
					int size = getArgsSize(args[0], symbolpool);
					if(size == -1) {
						return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
					}
					return new JLispData(symbolpool.getSymbolByString(""+size), JLispType.ATOM);
				}
			}else {
				Macro mac = (Macro)(args[0].data);
				if(JLispMacroName.QUOTE == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispMacroName.REVERSEQUOTE == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispMacroName.COMMA == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else if(JLispMacroName.SETQ == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispMacroName.SETF == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispMacroName.DO == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispMacroName.LET == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispMacroName.DEFUN == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispMacroName.DEFMACRO == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
				}else if(JLispMacroName.COMMAT == mac.macroName) {
					return new JLispData(symbolpool.getSymbolByString("1"), JLispType.ATOM);
				}else {
					int size = getArgsSize(args[0], symbolpool);
					if(size == -1) {
						return new JLispData(symbolpool.getSymbolByString("any"), JLispType.ATOM);
					}
					return new JLispData(symbolpool.getSymbolByString(""+size), JLispType.ATOM);
				}
			}
		}else if(JLispFunctionName.SLEEP == this.functionName) {
			int argsSize = args.length;
			if(argsSize != 1) {
				return new JLispData(new Error("The function \"sleep\" expected 1 arg, but found "+argsSize+" arg"), JLispType.ERROR);
			}
			if(JLispType.ATOM != args[0].type) {
				return new JLispData(new Error("The function \"sleep\" expected int number as arg"), JLispType.ERROR);
			}
			Atom atom = (Atom)(args[0].data);
			if(!atom.isNumber) {
				return new JLispData(new Error("The function \"sleep\" expected int number as arg"), JLispType.ERROR);
			}
			if(atom.name.contains(".")) {
				return new JLispData(new Error("The function \"sleep\" expected int number as arg"), JLispType.ERROR);
			}
			
			try {
				if(Integer.valueOf(atom.name).intValue() < 0) {
					return new JLispData(new Error("The function \"sleep\" expected positive integer as arg"), JLispType.ERROR);
				}
				Thread.sleep(Integer.valueOf(atom.name).longValue());
				return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
			} catch (NumberFormatException e) {
				// TODO Auto-generated catch block
				return new JLispData(new Error("NumberFormatException"), JLispType.ERROR);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				return new JLispData(new Error("InterruptedException"), JLispType.ERROR);
			}
		}else if(JLispFunctionName.TYPE == this.functionName) {
			int argsSize = args.length;
			if(argsSize != 1) {
				return new JLispData(new Error("The function \"type\" expected 1 arg, but found "+argsSize+" arg"), JLispType.ERROR);
			}
			return new JLispData(symbolpool.getSymbolByString(""+args[0].type), JLispType.ATOM);
		}else if(JLispFunctionName.IN == this.functionName) {
			int argsSize = args.length;
			if(argsSize != 0) {
				return new JLispData(new Error("The function \"in\" expected 0 arg, but found "+argsSize+" arg"), JLispType.ERROR);
			}
			Scanner sc = new Scanner(System.in);
			try{
				String str = sc.next();
				JLispData returnValue = Terminal.getDataFromString(str.trim(), symbolpool, functionPool, macroPool);
				return returnValue;
			}catch(Exception exp){
				return new JLispData(new Error(exp.getMessage()), JLispType.ERROR);
			}
		}else if(JLispFunctionName.DEBUG == this.functionName) {
			int argsSize = args.length;
			if(argsSize != 1) {
				return new JLispData(new Error("The function \"debug\" expected 1 arg, but found "+argsSize+" arg"), JLispType.ERROR);
			}
			if(JLispType.ATOM != args[0].type) {
				return new JLispData(new Error("The function \"debug\" expected int number as arg"), JLispType.ERROR);
			}
			Atom atom = (Atom)(args[0].data);
			if(!atom.isNumber) {
				if("log".equalsIgnoreCase(atom.name)) {
					functionPool.startDebug();
					return new JLispData(new Atom("LOGOPEN"), JLispType.ATOM);
				}else if("closelog".equalsIgnoreCase(atom.name)) {
					functionPool.closeDebug();
					return new JLispData(new Atom("LOGCLOSE"), JLispType.ATOM);
					
				}else {
					return new JLispData(new Error("The function \"debug\" expected int number as arg"), JLispType.ERROR);				
				}
			}
			if(atom.name.contains(".")) {
				return new JLispData(new Error("The function \"debug\" expected int number as arg"), JLispType.ERROR);
			}
			int debugarg = Integer.valueOf(atom.name).intValue();
			if(0 > debugarg) {
				switch(debugarg) {
				case -3:
					functionPool.startDebugMode();
					return new JLispData(symbolpool.getSymbolByString("DEBUGMODE"), JLispType.ATOM);
//					break;
				case -4:
					functionPool.closeDebugMode();
					return new JLispData(symbolpool.getSymbolByString("REPLMODE"), JLispType.ATOM);
//					break;
				default:
					break;
				}
			}
			return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
		}else {//鑷畾涔夊嚱鏁�,姣忚繍琛屼竴娆¤嚜瀹氫箟鍑芥暟锛岄兘瑕佸皢鍙傛暟鍒楄〃涓殑绗﹀彿鍏ユ爤骞跺嚭鏍堜竴娆�
			if(null == this.args && symbolpool.getSymbolByString("nil") == this.nil) {//濡傛灉鍙傛暟鍒楄〃涓虹┖鍒楄〃
				if(args != null && args.length > 0) {//濡傛灉鏈夊弬鏁版暟缁勪紶杩涙潵鐨勮瘽锛屽垯浜х敓涓�涓紓甯革紝浣嗕笉杩斿洖
					new Error("The customize function expected 0 args");
				}
				
				if(null == this.functionBodys || this.functionBodys.size() == 0) {//濡傛灉娌℃湁鍑芥暟浣撳垯鐩存帴杩斿洖鍘熷瓙鈥渘il鈥�
					return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
				}
				//鐩存帴杩愯鍑芥暟浣擄紙鑰冭檻闂寘锛�
				//闂寘鍏ユ爤
				closurePushStack();
				JLispData returnValue = null;
				for(JLispData body:this.functionBodys) {
					returnValue = body.eval(symbolpool, functionPool, macroPool);
					if(JLispType.ERROR == returnValue.type) {
						//解决函数因为函数体发生错误而提前退出时闭包或参数没有出栈的bug
						closurePopStack();
						//
						return returnValue;
					}
				}
				closurePopStack();
				//闂寘鍑烘爤
				return returnValue;
			}
			if(null == this.functionBodys || this.functionBodys.size() == 0) {//濡傛灉娌℃湁鍑芥暟浣撳垯鐩存帴杩斿洖鍘熷瓙鈥渘il鈥�
				return new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM);
			}
			pushValuesToArgs(args, symbolpool);//姣忚繍琛屼竴娆¤嚜瀹氫箟鍑芥暟锛岄兘瑕佸皢鍙傛暟鍒楄〃涓殑绗﹀彿鍏ユ爤涓�娆�
			closurePushStack();
			JLispData returnValue = null;
			for(JLispData body:this.functionBodys) {
				returnValue = body.eval(symbolpool, functionPool, macroPool);
				if(JLispType.ERROR == returnValue.type) {
					//解决函数因为函数体发生错误而提前退出时闭包或参数没有出栈的bug
					closurePopStack();
					popValuesFromArgs(symbolpool);//姣忚繍琛屼竴娆¤嚜瀹氫箟鍑芥暟锛岄兘瑕佸皢鍙傛暟鍒楄〃涓殑绗﹀彿鍑烘爤涓�娆�
					//
					return returnValue;
				}
			}
			closurePopStack();
			popValuesFromArgs(symbolpool);//姣忚繍琛屼竴娆¤嚜瀹氫箟鍑芥暟锛岄兘瑕佸皢鍙傛暟鍒楄〃涓殑绗﹀彿鍑烘爤涓�娆�
			return returnValue;
		}
		return null;
	}
	private int getArgsSize(JLispData funOrMac, SymbolPool symbolPool) {
		if(JLispType.FUNCTION == funOrMac.type) {
			Function fun = (Function)(funOrMac.data);
			if(null != fun.nil) {
				return 0;
			}else {
				if(fun.args.indexOfAtom(symbolPool.getSymbolByString("&rest")) == -1) {
					return fun.args.getLength();
				}else {
					return -1;
				}
			}
		}else if(JLispType.MACRO == funOrMac.type) {
			Macro mac = (Macro)(funOrMac.data);
			if(null != mac.nil) {
				return 0;
			}else {
				if(mac.args.indexOfAtom(symbolPool.getSymbolByString("&rest")) == -1) {
					return mac.args.getLength();
				}else {
					return -1;
				}
			}
		}else {
			return -2;
		}
	}
	private String toRightExpr(String expr) {
		
		/*
		 * 棣栧厛灏嗚幏鍙栧埌鐨勫瓧绗︿覆涓墍鏈夋崲琛岀鐢ㄧ┖鏍兼浛浠�
		 */
		expr = expr.replace("\r\n", " ");
		expr = expr.replace("\n", " ");
		expr = expr.replace("\t", " ");
		expr = expr.replace("（", "(");
		expr = expr.replace("）", ")");
		/*
		 * 鐒跺悗灏嗗涓┖鏍肩敤涓�涓┖鏍兼浛浠�
		 */
		int spaceSize = getSerialSpaceSize(expr);
		if(spaceSize > 1) {
			for(int size = spaceSize;size > 1;size--) {
				String sizeSpace = "";
				for(int i = 0;i < size;i++) {
					sizeSpace += " ";
				}
				expr = expr.replace(sizeSpace, " ");
			}
		}
		expr = expr.replace("( )", "()");
		expr = expr.replace("( (", "((");//闇�瑕佹浛鎹袱閬�
		expr = expr.replace("( (", "((");
		expr = expr.replace(") )", "))");//闇�瑕佹浛鎹袱閬�
		expr = expr.replace(") )", "))");
		if(" ".equals(expr)) {
			return "";
		}
		return expr;	
	}
	private int getSerialSpaceSize(String expr) {
		int maxSize = 0;
		int size = 0;
		for(int i = 0;i < expr.length();i++) {
			if(expr.charAt(i) == ' ') {
				size += 1;
				if(size > maxSize) {
					maxSize = size;
				}
			}else  {
				size = 0;
			}
		}
		return maxSize;
	}
	private String codeString(String fileName) throws Exception {
        BufferedInputStream bin = new BufferedInputStream(new FileInputStream(fileName));
        int p = (bin.read() << 8) + bin.read();
        bin.close();
        String code = null;
        switch (p) {
        case 0xefbb:
            code = "UTF-8";
            break;
        case 0xfffe:
            code = "Unicode";
            break;
        case 0xfeff:
            code = "UTF-16BE";
            break;
        default:
            code = "GBK";
        }
        return code;
    }
	private String getPathFromCons(Cons cons) {

		
		String path = "";
		for(int i = 0;i < cons.getLength();i++) {
			if(i == cons.getLength() - 1) {
				path += Terminal.getStringFromData(cons.getItemById(i));
			}else {
				path += Terminal.getStringFromData(cons.getItemById(i)) + "\\";		
			}
		}
		return path;
	}
	private int kindOfCons(Cons cons) {
		JLispData data = cons.getItemById(0);
		if(JLispType.ATOM != data.type) {//濡傛灉涓嶆槸鍘熷瓙锛屽垯鏄櫘閫氬垪琛�
			return 0;
		}
		Atom atom = (Atom)(data.data);
		if(null == atom.symbolValues) {//濡傛灉鍊兼爤涓虹┖锛屽垯鏄壒娈婂師瀛愶紝鍚屾牱鏄櫘閫氬垪琛�
			return 0;
		}
		if(null == atom.functionEval()) {//濡傛灉娌℃湁鍑芥暟鍊硷紝涔熸槸鏅�氬垪琛�
			return 0;
		}
		JLispData FunOrMac = atom.functionEval();
		if(JLispType.FUNCTION == FunOrMac.type) {//濡傛灉鏄嚱鏁板垪琛ㄨ繑鍥�1
			return 1;
		}else if(JLispType.MACRO == FunOrMac.type) {//濡傛灉鏄畯鍒楄〃杩斿洖2
			return 2;
		}
		return 0;
	}
	private void closurePushStack() {
		if(null == this.closure || this.closure.size() == 0) {
			return;
		}
		for(Atom closureAtom:this.closure) {
			closureAtom.setValue(closureAtom.isClosureAtom.value);
		}
	}
	private void closurePopStack() {
		if(null == this.closure || this.closure.size() == 0) {
			return;
		}
		for(Atom closureAtom:this.closure) {
			closureAtom.pop();
		}
	}
	private void pushValuesToArgs(JLispData[] args, SymbolPool symbolpool) {
		/*
		 * 棣栧厛妫�鏌ュ弬鏁板垪琛ㄤ腑鏈夋病鏈� &rest 鍘熷瓙
		 */
		if(this.args.indexOfAtom(symbolpool.getSymbolByString("&rest")) == -1) {//鍗充唬琛ㄥ弬鏁板垪琛ㄤ腑娌℃湁&rest鍘熷瓙
			/*
			 * 濡傛灉鍙傛暟鍒楄〃鐨勯暱搴﹀拰瀹為檯浼犺繘鏉ョ殑鍙傛暟鏁扮粍鐨勯暱搴︿笉鐩哥瓑锛屽垯浜х敓涓�涓敊璇紝浣嗕笉杩斿洖锛屽洜涓鸿鍑芥暟鏄┖杩斿洖鍊煎嚱鏁帮紝濡傛灉瀹為檯鍙傛暟涓暟灏忎簬褰㈠弬鍒楄〃闀垮害锛岄偅涔堝浣欑殑褰㈠弬
			 * 灏嗕細琚帇鍏il鍘熷瓙锛屽鏋滃疄闄呭弬鏁颁釜鏁板浣欏舰鍙傚垪琛ㄩ暱搴﹀垯澶氫綑鐨勫疄鍙備笉浣滃鐞�
			 */
			if(this.args.getLength() > args.length) {//褰㈠弬鍒楄〃闀垮害澶т簬瀹為檯鍙傛暟鏁扮粍鐨勯暱搴�
//				new Error("a customize function expected more args or it will be transformed Atom \"nil\"");//姝ゅ浜х敓涓�涓敊璇絾涓嶈繑鍥烇紝绋嬪簭浼氱户缁繍琛岋紝浣嗗湪缁堢浼氭湁鐩稿簲鎻愮ず
				for(int i = 0;i < this.args.getLength();i++) {//渚濇杩唬姣忎釜鍙傛暟鍒楄〃鐨勭储寮曞��
					if(i >= args.length) {//濡傛灉褰撳墠绱㈠紩鍊煎ぇ浜庢垨绛変簬鏁扮粍鐨勯暱搴︼紝鍒欐剰鍛崇潃姝ゆ椂闇�瑕佸皢褰㈠弬鍒楄〃涓殑鍘熷瓙鍘嬪叆鍘熷瓙nil
						/*
						 * 榛樿鍙傛暟鍒楄〃涓墍鏈夊厓绱犵殑鏁版嵁绫诲瀷閮芥槸鍘熷瓙锛岃繖涓潯浠惰鍦ㄦ瀯閫犱竴涓嚱鏁版椂灏辫婊¤冻
						 */
						((Atom)(this.args.getItemById(i).data)).setValue(new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM));
					}else {
						((Atom)(this.args.getItemById(i).data)).setValue(args[i]);
						
					}
				}
			}else {//褰㈠弬鍒楄〃闀垮害灏忎簬鎴栫瓑浜庡疄闄呭弬鏁版暟缁勭殑闀垮害
				for(int i = 0;i < this.args.getLength();i++) {//渚濇杩唬姣忎釜鍙傛暟鍒楄〃鐨勭储寮曞��
					
					((Atom)(this.args.getItemById(i).data)).setValue(args[i]);
				}
			}
		}else {//濡傛灉鍙傛暟鍒楄〃涓師瀛�&rest鐨勭储寮曞�间笉涓�-1鐨勮瘽锛岄偅涔堜唬琛ㄥ弬鏁板垪琛ㄤ腑鏈�&rest鍘熷瓙锛屽苟涓斿畠鐨勪綅缃竴瀹氬浜庡弬鏁板垪琛ㄧ殑鍊掓暟绗簩涓綅缃笂锛岃繖涓�鐐瑰悓鏍烽渶瑕佸湪鏋勯�犺鍑芥暟鏃朵繚璇�
			if(this.args.getLength() - args.length > 1) {//濡傛灉褰㈠弬鍒楄〃鐨勯暱搴︽瘮瀹為檯鍙傛暟鏁扮粍鐨勯暱搴﹀涓や釜鎴栦袱涓互涓�
				for(int i = 0;i < this.args.getLength();i++) {
					if(i >= args.length) {
						if(i == this.args.getLength() - 2) {//姝ゆ椂鐨勭储寮曞�煎垰濂芥槸&rest鍘熷瓙鐨勭储寮曞�硷紝涓嶅仛澶勭悊缁х画涓嬩竴灞傚惊鐜�
							continue;
						}else {
							((Atom)(this.args.getItemById(i).data)).setValue(new JLispData(symbolpool.getSymbolByString("nil"), JLispType.ATOM));
						}
					}else {
						((Atom)(this.args.getItemById(i).data)).setValue(args[i]);
					}
				}
			}else {
				/*
				 * 鍒涘缓涓�涓暟缁勭敤鏉ユ瀯寤哄垪琛�
				 */
				JLispData[] endOfArgs = new JLispData[args.length - this.args.getLength() + 2];
				for(int i = 0;i < this.args.getLength() - 2;i++) {
					((Atom)(this.args.getItemById(i).data)).setValue(args[i]);
				}
				for(int i = this.args.getLength() - 2,j = 0;j < endOfArgs.length;i++,j++) {
					endOfArgs[j] = args[i];
				}
				((Atom)(this.args.getItemById(this.args.getLength() - 1).data)).setValue(new JLispData(new Cons(endOfArgs, symbolpool.getSymbolByString("nil")), JLispType.CONS));
			}	
		}
	}
	private void popValuesFromArgs(SymbolPool symbolpool) {
		//if(this.args.indexOfAtom(symbolpool.getSymbolByString("&rest")) == -1) {//鍗充唬琛ㄥ弬鏁板垪琛ㄤ腑娌℃湁&rest鍘熷瓙
		for(int i = 0;i < this.args.getLength();i++) {
			if("&rest".equalsIgnoreCase(((Atom)(this.args.getItemById(i).data)).name)) {
				continue;
			}
			((Atom)(this.args.getItemById(i).data)).pop();
		}
	//}
	}
	
	private boolean less(Atom arg1, Atom arg2) {
		try {
			return Double.valueOf(arg1.name) < Double.valueOf(arg2.name);
		}catch(NumberFormatException e) {
			return false;
		}
	}
	private boolean more(Atom arg1, Atom arg2) {
		try {
			return Double.valueOf(arg1.name) > Double.valueOf(arg2.name);
		}catch(NumberFormatException e) {
			return false;
		}
	}
	
	private boolean eqNum(Atom arg1, Atom arg2) {
		try {
			return Double.valueOf(arg1.name).doubleValue() == Double.valueOf(arg2.name).doubleValue();
		}catch(NumberFormatException e) {
			return false;
		}
	}
	
	private Atom add(Atom arg1, Atom arg2, SymbolPool symbolpool) {
		if(arg1.name.contains(".") || arg2.name.contains(".")) {//濡傛灉涓や釜鍙傛暟鏈変竴涓槸灏忔暟鐨勮瘽锛屽垯缁熶竴鐢╠ouble鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Double.valueOf(arg1.name) + Double.valueOf(arg2.name)));
			}catch(NumberFormatException exe) {
				return symbolpool.getSymbolByString("NumberFormatException");
			}
		}else {//鍚﹀垯鐢╥nt鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Integer.valueOf(arg1.name) + Integer.valueOf(arg2.name)));
			}catch(NumberFormatException e) {
				try {
					return symbolpool.getSymbolByString(String.valueOf(Long.valueOf(arg1.name) + Long.valueOf(arg2.name)));
				}catch(NumberFormatException exe) {
					return symbolpool.getSymbolByString("NumberFormatException");
				}
			}
		}
	}
	
	
	
	/*
	 * 璋冪敤杩欎簺鍔犲噺涔橀櫎鏂规硶鍓嶆湡瑕佷繚璇佺殑鏉′欢
	 * 鍙傛暟涓暟
	 * 鏄暟瀛楀師瀛�
	 * 闄ゆ暟涓嶄负0
	 */
	private Atom sub(Atom arg1, Atom arg2, SymbolPool symbolpool) {
		if(arg1.name.contains(".") || arg2.name.contains(".")) {//濡傛灉涓や釜鍙傛暟鏈変竴涓槸灏忔暟鐨勮瘽锛屽垯缁熶竴鐢╠ouble鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Double.valueOf(arg1.name) - Double.valueOf(arg2.name)));
			}catch(NumberFormatException exe) {
				return symbolpool.getSymbolByString("NumberFormatException");
			}
		}else {//鍚﹀垯鐢╥nt鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Integer.valueOf(arg1.name) - Integer.valueOf(arg2.name)));
			}catch(NumberFormatException e) {
				try {
					return symbolpool.getSymbolByString(String.valueOf(Long.valueOf(arg1.name) - Long.valueOf(arg2.name)));
				}catch(NumberFormatException exe) {
					return symbolpool.getSymbolByString("NumberFormatException");
				}
			}
		}
	}
	private Atom mul(Atom arg1, Atom arg2, SymbolPool symbolpool) {
		if(arg1.name.contains(".") || arg2.name.contains(".")) {//濡傛灉涓や釜鍙傛暟鏈変竴涓槸灏忔暟鐨勮瘽锛屽垯缁熶竴鐢╠ouble鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Double.valueOf(arg1.name) * Double.valueOf(arg2.name)));
			}catch(NumberFormatException exe) {
				return symbolpool.getSymbolByString("NumberFormatException");
			}
		}else {//鍚﹀垯鐢╥nt鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Integer.valueOf(arg1.name) * Integer.valueOf(arg2.name)));
			}catch(NumberFormatException e) {
				try {
					return symbolpool.getSymbolByString(String.valueOf(Long.valueOf(arg1.name) * Long.valueOf(arg2.name)));
				}catch(NumberFormatException exe) {
					return symbolpool.getSymbolByString("NumberFormatException");
				}
			}
		}
	}
	private Atom div(Atom arg1, Atom arg2, SymbolPool symbolpool) {
		if(arg1.name.contains(".") || arg2.name.contains(".")) {//濡傛灉涓や釜鍙傛暟鏈変竴涓槸灏忔暟鐨勮瘽锛屽垯缁熶竴鐢╠ouble鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Double.valueOf(arg1.name) / Double.valueOf(arg2.name)));
			}catch(NumberFormatException exe) {
				return symbolpool.getSymbolByString("NumberFormatException");
			}
			
		}else {//鍚﹀垯鐢╥nt鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Integer.valueOf(arg1.name) / Integer.valueOf(arg2.name)));
			}catch(NumberFormatException e) {
				try {
					return symbolpool.getSymbolByString(String.valueOf(Long.valueOf(arg1.name) / Long.valueOf(arg2.name)));
				}catch(NumberFormatException exe) {
					return symbolpool.getSymbolByString("NumberFormatException");
				}
			}
		}
	}
	
	private Atom mod(Atom arg1, Atom arg2, SymbolPool symbolpool) {
		if(arg1.name.contains(".") || arg2.name.contains(".")) {//濡傛灉涓や釜鍙傛暟鏈変竴涓槸灏忔暟鐨勮瘽锛屽垯缁熶竴鐢╠ouble鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Double.valueOf(arg1.name) % Double.valueOf(arg2.name)));
			}catch(NumberFormatException exe) {
				return symbolpool.getSymbolByString("NumberFormatException");
			}
			
		}else {//鍚﹀垯鐢╥nt鍊煎鐞�
			try {
				return symbolpool.getSymbolByString(String.valueOf(Integer.valueOf(arg1.name) % Integer.valueOf(arg2.name)));
			}catch(NumberFormatException e) {
				try {
					return symbolpool.getSymbolByString(String.valueOf(Long.valueOf(arg1.name) % Long.valueOf(arg2.name)));
				}catch(NumberFormatException exe) {
					return symbolpool.getSymbolByString("NumberFormatException");
				}
			}
		}
	}
	
	
}
